package com.bjx.system.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjx.api.system.domain.query.UserQuery;
import com.bjx.common.security.domain.UserPostVO;
import com.bjx.api.system.domain.vo.UserRoleVO;
import com.bjx.api.system.domain.vo.UserVO;
import com.bjx.common.core.constant.FrameConst;
import com.bjx.common.core.exception.BJXException;
import com.bjx.common.security.domain.LoginUserVO;
import com.bjx.common.security.util.LoginUtil;
import com.bjx.system.domain.bo.UserBO;
import com.bjx.system.domain.entity.UserEntity;
import com.bjx.system.domain.vo.OrgVO;
import com.bjx.system.domain.vo.UpdatePasswordVO;
import com.bjx.system.mapper.UserMapper;
import com.bjx.system.service.IOrgService;
import com.bjx.system.service.IUserPostService;
import com.bjx.system.service.IUserRoleService;
import com.bjx.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @desc: 用户服务实现
 * @author: liushuai
 * @date: 2022/7/6 17:06
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserEntity> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Value("${encryption.public}")
    private String publicKey;

    @Value("${encryption.private}")
    private String privateKey;

    @Resource
    private IOrgService orgService;

    @Resource
    private IUserPostService userPostService;

    @Resource
    private IUserRoleService userRoleService;


    @Override
    public void insertUser(UserVO userVO) {
        Long userCount = selectUserCountByUsername(userVO.getUsername());
        if (userCount > 0) {
            throw new BJXException("登录用户名已存在");
        }
        if (StrUtil.isEmpty(userVO.getPassword())) {
            userVO.setPassword(FrameConst.DEFAULT_PASSWORD);
        }
        //设置所属公司
        OrgVO orgVO = orgService.selectOrgByOrgId(Long.valueOf(userVO.getOrgId()));
        userVO.setComId(orgVO.getComId());
        //加密密码
        userVO.setPassword(SaSecureUtil.rsaEncryptByPublic(publicKey, userVO.getPassword()));
        UserEntity userEntity = Convert.convert(UserEntity.class, userVO);
        this.save(userEntity);
    }

    @Override
    public UserVO selectUserInfoByUsername(String username) {
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, username);
        UserEntity userEntity = userMapper.selectOne(wrapper);
        UserVO userVO = Convert.convert(UserVO.class, userEntity);
        //查询用户角色编号列表
        List<String> roles = listUserRoleCodeByUserId(userEntity.getUserId());
        userVO.setRoles(roles);
        //查询用户权限标识列表
        List<String> auths = listUserAuthFlagByUserId(userEntity.getUserId());
        userVO.setAuths(auths);
        //查询用户职位列表
        List<UserPostVO> posts = listUserPostByUserId(userEntity.getUserId());
        userVO.setPosts(posts);
        return userVO;
    }


    @Override
    public UserVO selectUserInfoByUserId(Long userId) {
        UserEntity userEntity = userMapper.selectById(userId);
        UserVO userVO = Convert.convert(UserVO.class, userEntity);
        userVO.setPassword(null);
        return userVO;
    }

    @Override
    public void updateUser(UserVO userVO) {
        if (StrUtil.isNotEmpty(userVO.getUsername())) {
            LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(UserEntity::getUsername, userVO.getUsername());
            UserEntity userEntity = userMapper.selectOne(wrapper);
            if (ObjectUtil.isNotNull(userEntity) && !userVO.getUserId().equals(String.valueOf(userEntity.getUserId()))) {
                throw new BJXException("用户登录名已存在");
            }
        }
        //设置所属公司
        OrgVO orgVO = orgService.selectOrgByOrgId(Long.valueOf(userVO.getOrgId()));
        userVO.setComId(orgVO.getComId());
        UserEntity userEntity = Convert.convert(UserEntity.class, userVO);
        if (StrUtil.isNotEmpty(userEntity.getPassword())) {
            String newPassword = SaSecureUtil.rsaEncryptByPublic(publicKey, userEntity.getPassword());
            userEntity.setPassword(newPassword);
        }
        userMapper.updateById(userEntity);
    }

    @Override
    public void deleteUserByUserId(Long userId) {
        userMapper.deleteById(userId);
    }

    @Override
    public List<UserVO> listUserInfoByOrgId(Long orgId) {
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getOrgId, orgId);
        List<UserEntity> userEntities = userMapper.selectList(wrapper);
        List<UserVO> userVOS = Convert.toList(UserVO.class, userEntities);
        return userVOS;
    }

    @Override
    public void updatePassword(UpdatePasswordVO updatePasswordVO) {
        if (!updatePasswordVO.originalPassword.equals(updatePasswordVO.getRepetitionPassword())) {
            throw new BJXException("两次输入的密码不一致");
        }
        LoginUserVO loginUserVO = LoginUtil.loginInfo();
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(UserEntity::getPassword);
        wrapper.eq(UserEntity::getUserId, Long.valueOf(loginUserVO.getUserId()));
        UserEntity userEntity = userMapper.selectOne(wrapper);
        String password = SaSecureUtil.rsaDecryptByPrivate(privateKey, userEntity.getPassword());
        if (!password.equals(updatePasswordVO.getOriginalPassword())) {
            throw new BJXException("原密码错误");
        }
        //加密密码
        String newPassword = SaSecureUtil.rsaEncryptByPublic(publicKey, updatePasswordVO.getNewPassword());
        LambdaUpdateWrapper<UserEntity> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(UserEntity::getUserId, Long.valueOf(loginUserVO.getUserId()));
        userMapper.update(UserEntity.builder()
                .password(newPassword)
                .build(), wrapper);
    }

    @Override
    public Page<UserVO> listUserPage(UserQuery userQuery) {
        Page<UserVO> pageUser = userMapper.listUserPage(userQuery.getPage(), userQuery);
        return pageUser;
    }

    @Override
    public void saveUserPost(UserVO userVO) {
        if (StrUtil.isEmpty(userVO.getUserId())) {
            throw new BJXException("用户Id不能为空");
        }
        userPostService.saveUserPostBatch(userVO.getPosts(), Long.valueOf(userVO.getUserId()));
    }

    @Override
    public List<UserPostVO> listUserPost(Long userId) {
        List<UserPostVO> userPostVOS = userPostService.listUserPost(userId);
        return userPostVOS;

    }

    @Override
    public void saveUserRole(UserVO userVO) {
        userRoleService.saveUserRoleBatch(userVO.getRoleIds(), Long.valueOf(userVO.getUserId()));
    }

    @Override
    public List<UserRoleVO> listUserRoleByUserId(Long userId) {
        List<UserRoleVO> vos = userRoleService.listUserRoleByUserId(userId);
        return vos;
    }

    @Override
    public List<Tree<String>> listUserTreeByOrgId(Long orgId) {
        List<UserBO> userList = userMapper.listUserTreeByOrgId(orgId);
        if(FrameConst.ROOT.intValue() != orgId){
            OrgVO orgVO = orgService.selectOrgByOrgId(orgId);
            orgId = Long.valueOf(orgVO.getPid());
        }
        //转换器
        List<Tree<String>> treeNodes = TreeUtil.build(userList, "-"+orgId, new TreeNodeConfig(),
                (treeNode, tree) -> {
                    if("org".equals(treeNode.getType())){
                        tree.setId("-"+treeNode.getId());
                        tree.setParentId("-"+treeNode.getPid());
                    }else{
                        tree.setId(treeNode.getId());
                        tree.setParentId("-"+treeNode.getPid());
                    }
                    tree.setWeight(treeNode.getCreateDate());
                    tree.setName(treeNode.getName());
                    tree.putExtra("type", treeNode.getType());
                    tree.putExtra("disabled", FrameConst.STR_NO.equals(treeNode.getEnabled()));
                });
        return treeNodes;
    }

    @Override
    public List<UserVO> listUserVOByIds(UserQuery userQuery) {
        if(CollectionUtil.isEmpty(userQuery.getUserIds())){
            return new ArrayList<UserVO>();
        }
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(UserEntity::getUserId,userQuery.getUserIds());
        List<UserEntity> userEntities = userMapper.selectList(wrapper);
        List<UserVO> userVOS = Convert.toList(UserVO.class,userEntities);
        return userVOS;
    }

    @Override
    public List<UserVO> listUserVOByOrgAndPosts(UserQuery userQuery) {
        Map<Long, List<Long>> queryMap = userQuery.getQueryMap();
        if(CollectionUtil.isEmpty(queryMap)){
            return  new ArrayList<>();
        }
        Iterator<Map.Entry<Long, List<Long>>> iterator = queryMap.entrySet().iterator();
        List<UserVO> users = new ArrayList<>();
        while (iterator.hasNext()){
            Map.Entry<Long, List<Long>> next = iterator.next();
            List<UserVO> list = userMapper.listUserVOByOrgAndPosts(next.getKey(),next.getValue());
            users.addAll(list);
        }
        return users;
    }

    @Override
    public List<UserVO> listUserVOByComAndPosts(UserQuery userQuery) {
        Map<Long, List<Long>> queryMap = userQuery.getQueryMap();
        if(CollectionUtil.isEmpty(queryMap)){
            return  new ArrayList<>();
        }
        Iterator<Map.Entry<Long, List<Long>>> iterator = queryMap.entrySet().iterator();
        List<UserVO> users = new ArrayList<>();
        while (iterator.hasNext()){
            Map.Entry<Long, List<Long>> next = iterator.next();
            List<UserVO> list = userMapper.listUserVOByComAndPosts(next.getKey(),next.getValue());
            users.addAll(list);
        }
        return users;
    }

    @Override
    public List<UserVO> listUserVOByRoleIds(UserQuery userQuery) {
        List<Long> roleIds = userQuery.getRoleIds();
        if(CollectionUtil.isEmpty(roleIds)){
            return new ArrayList<UserVO>();
        }
        List<UserVO> users = userMapper.listUserVOByRoleIds(roleIds);
        return users;
    }

    @Override
    public List<UserVO> listUserVOByPostIds(UserQuery userQuery) {
        List<Long> postIds = userQuery.getPostIds();
        if(CollectionUtil.isEmpty(postIds)){
            return new ArrayList<UserVO>();
        }
        List<UserVO> users = userMapper.listUserVOByPostIds(postIds);
        return users;
    }

    @Override
    public List<UserVO> listUserVOByOrgAndRoleIds(UserQuery userQuery) {
        Map<Long, List<Long>> queryMap = userQuery.getQueryMap();
        if(CollectionUtil.isEmpty(queryMap)){
            return  new ArrayList<>();
        }
        Iterator<Map.Entry<Long, List<Long>>> iterator = queryMap.entrySet().iterator();
        List<UserVO> users = new ArrayList<>();
        while (iterator.hasNext()){
            Map.Entry<Long, List<Long>> next = iterator.next();
            List<UserVO> list = userMapper.listUserVOByOrgAndRoleIds(next.getKey(),next.getValue());
            users.addAll(list);
        }
        return users;
    }

    @Override
    public List<UserVO> listUserVOByComAndRoleIds(UserQuery userQuery) {
        Map<Long, List<Long>> queryMap = userQuery.getQueryMap();
        if(CollectionUtil.isEmpty(queryMap)){
            return  new ArrayList<>();
        }
        Iterator<Map.Entry<Long, List<Long>>> iterator = queryMap.entrySet().iterator();
        List<UserVO> users = new ArrayList<>();
        while (iterator.hasNext()){
            Map.Entry<Long, List<Long>> next = iterator.next();
            List<UserVO> list = userMapper.listUserVOByComAndRoleIds(next.getKey(),next.getValue());
            users.addAll(list);
        }
        return users;
    }



    /**
     * 根据登录名查询用户
     *
     * @param username
     * @return: java.lang.Long
     * @Author: liushuai
     * @Date: 2022/7/6 17:23
     */
    public Long selectUserCountByUsername(String username) {
        LambdaQueryWrapper<UserEntity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserEntity::getUsername, username);
        return userMapper.selectCount(wrapper);
    }

    /**
     * 根据用户id查询角色编号
     *
     * @param userId
     * @return: java.util.List<java.lang.String>
     * @Author: liushuai
     * @Date: 2022/10/19 15:20
     */
    public List<String> listUserRoleCodeByUserId(Long userId) {
        List<String> roleCodes = userMapper.listUserRoleCodeByUserId(userId);
        return roleCodes;
    }

    /**
     * 根据用户id查询用户权限标识
     *
     * @param userId
     * @return: java.util.List<java.lang.String>
     * @Author: liushuai
     * @Date: 2022/10/19 15:21
     */
    private List<String> listUserAuthFlagByUserId(Long userId) {
        List<String> authFlags = userMapper.listUserAuthFlagByUserId(userId);
        return authFlags;
    }

    /**
     * 根据用户id获取用户职位列表
     *
     * @param userId
     * @return: java.util.List<com.bjx.api.system.domain.vo.UserPostVO>
     * @Author: liushuai
     * @Date: 2022/10/19 15:31
     */
    private List<UserPostVO> listUserPostByUserId(Long userId) {
        List<UserPostVO> posts = userMapper.listUserPostByUserId(userId);
        return posts;
    }

}
